//
//  WXAnimationView.m
//  ParentsCommunity
//
//  Created by tianlong on 2018/7/3.
//  Copyright © 2018年 XES. All rights reserved.
//

#import "WXAnimationView.h"
#import "Masonry.h"
#import <YYWeakProxy.h>

#define WXAV_CoverViewAlpha 0.6

@interface WXAnimationView ()
@property (nonatomic, assign) NSInteger playedCount;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic, assign) CGFloat speed;
@property (nonatomic, assign) NSInteger repeatCount;
@property (nonatomic,   copy) void (^completion)(BOOL finished);
@property (nonatomic, assign) BOOL isStop;
@end

@implementation WXAnimationView

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        self.playedCount = 0;
        // 按层级先后创建容器以及其他子视图
        [self setupBottomView];
        [self setupMiddleView];
        [self setupTopView];
    }
    return self;
}

- (void)setupBottomView {
    UIView *bottomView = [[UIView alloc] init];
    [self addSubview:bottomView];
    [self setBottomView:bottomView];
    
    UIImageView *backgroundImageView = [[UIImageView alloc] init];
    [backgroundImageView setHidden:YES];
    [bottomView addSubview:backgroundImageView];
    [self setBackgroundImageView:backgroundImageView];
    
    UIImageView *coverView = [[UIImageView alloc] init];
    [coverView setAlpha:WXAV_CoverViewAlpha];
    [coverView setHidden:YES];
    [coverView setBackgroundColor:[UIColor blackColor]];
    [bottomView addSubview:coverView];
    [self setCoverView:coverView];
}

- (void)setupMiddleView {
    UIView *mid = [[UIView alloc] init];
    [self addSubview:mid];
    [self setMiddleView:mid];
}

- (void)setupTopView {
    UIView *topView = [[UIView alloc] init];
    [self addSubview:topView];
    [self setTopView:topView];
    
    UIButton *btn = [[UIButton alloc] init];
    [btn addTarget:self action:@selector(clickedCloseBtn) forControlEvents:UIControlEventTouchDown];
    btn.hidden = YES;
    [btn setImage:[UIImage imageNamed:@"livevideo_alertview_close_bth_normal"] forState:UIControlStateNormal];
    [topView addSubview:btn];
    [self setCloseBtn:btn];
}

#pragma mark - lazyLoad
- (WXLOTAnimationView *)playView{
    if (!_playView) {
        _playView = [[WXLOTAnimationView alloc] init];
        [self.middleView addSubview:_playView];
        [_playView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.left.top.bottom.right.offset(0);
        }];
    }
    return _playView;
}

#pragma mark - 布局
- (void)layoutSubviews{
    [super layoutSubviews];
    
    // 底部
    [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.right.offset(0);
    }];
    [self.backgroundImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.right.offset(0);
    }];
    [self.coverView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.right.offset(0);
    }];
    
    // 中间
    [self.middleView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.right.offset(0);
    }];
    
    // 顶部
    [self.topView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.left.bottom.right.offset(0);
    }];
    [self.closeBtn mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.right.offset(0);
        make.width.height.offset(50);
    }];
}

- (instancetype)initWithJson:(NSString *)json
                       speed:(CGFloat)speed
                 repeatCount:(NSInteger)repeatCount
                  completion:(void (^)(BOOL finished))completion {
    self = [super init];
    if (self) {
        self.animationJson = json;
        self.speed = speed;
        self.repeatCount = repeatCount;
        self.completion = completion;
        [self playWithJson:json speed:speed repeatCount:repeatCount completion:completion];
    }
    return self;
}

#pragma mark - 播放动画核心代码
- (void)playWithJson:(NSString *)json
               speed:(CGFloat)speed
         repeatCount:(NSInteger)repeatCount
          completion:(void (^)(BOOL finished))completion {
    if (json) {
        __weak typeof(self)selfWeak = self;
        self.animationJson = json;
        [self.playView setAnimationNamed:self.animationJson];
        [self.playView setAnimationSpeed:speed];
        [self.playView logHierarchyKeypaths];
        [self.playView forceDrawingUpdate];
        [self.playView setLoopAnimation:NO];
        [self.playView setCompletionBlock:^(BOOL animationFinished) {
            [selfWeak animationLoopWithRepeatCount:repeatCount completion:completion];
        }];
    }
}

- (void)animationLoopWithRepeatCount:(NSInteger)repeatCount completion:(void (^)(BOOL finished))completion{
    
    [self stopDisplayLink];
    
    if (self.isStop) {
        return;
    }
    
    __weak typeof(self)selfWeak = self;
    
    if (repeatCount <= 0) {
        if (completion) {
            completion(YES);
        }
    }else if(repeatCount > 0) {
        if (self.playedCount == repeatCount) {
            self.playedCount = 0;
            if (completion) {
                completion(YES);
            }
            return;
        }
        [self.playView play];
        [self startDisplayLink];
        self.playedCount += 1;
        [self.playView setCompletionBlock:^(BOOL animationFinished) {
            if (selfWeak.isStop) {
                [selfWeak stopDisplayLink];
                return;
            }
            [selfWeak animationLoopWithRepeatCount:repeatCount completion:completion];
        }];
    }
}

- (void)clickedCloseBtn {
    if (self.clickedCloseBlock) {
        self.clickedCloseBlock();
    }
}

- (void)play{
    self.isAnimating = YES;
    self.isStop = NO;
    [self.playView play];
    [self startDisplayLink];
}

- (void)pause{
    [self.playView pause];
    [self stopDisplayLink];
    self.isAnimating = NO;
}

- (void)stop{
    self.isAnimating    = NO;
    self.isStop         = YES;
    self.playedCount    = 0;
    
    [self stopDisplayLink];
    [self.coverView setHidden:YES];
    [self.backgroundImageView setHidden:YES];
    
    [self.playView stop];
    [self.playView removeFromSuperview];
    self.playView = nil;
}

#pragma mark - 绑定视图到指定路径的图层
- (void)bindingUIView:(UIView *)view
           forKeyPath:(NSString *)keyPath
            imageName:(NSString *)imageName{
    LOTKeypath *keypath = [LOTKeypath keypathWithString:keyPath];
    if (keypath) {
        if (view) {
            [self.playView addSubview:view toKeypathLayer:keypath];
            CGRect frame = [self fetchImageEntityInfile:self.animationJson imageName:imageName];
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                make.left   .offset(frame.origin.x);
                make.top    .offset(frame.origin.y);
                make.width  .offset(frame.size.width);
                make.height .offset(frame.size.height);
            }];
        }
    }
}

- (CGRect)fetchImageEntityInfile:(NSString *)fileName imageName:(NSString *)imageName{
    NSError *error;
    NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"json"];
    NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
    
    if (@available(iOS 9.0, *)) {
        if (!jsonData) {
            jsonData = [[NSDataAsset alloc] initWithName:fileName].data;
        }
    }
    NSDictionary  *jsonObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
                                                                           options:0 error:&error] : nil;
    CGRect rect = CGRectZero;
    if (jsonObject && !error) {
        NSArray *assets = [jsonObject objectForKey:@"assets"];
        for (int i = 0; i <assets.count; i++) {
            NSDictionary *assetsDict = [assets objectAtIndex:i];
            if (assetsDict && [assetsDict isKindOfClass:[NSDictionary class]]) {
                NSString *p = [assetsDict objectForKey:@"p"];
                if (p) {
                    if ([p isEqualToString:imageName]) {
                        NSString *widthStr = [assetsDict objectForKey:@"w"];
                        NSString *heightStr = [assetsDict objectForKey:@"h"];
                        if (widthStr && heightStr) {
                            rect.size.width = widthStr.floatValue;
                            rect.size.height = heightStr.floatValue;
                        }
                        break;
                    }
                }
            }
        }
    }
    return rect;
}

#pragma mark - 通过json获取动画layer层的数组
- (NSDictionary *)getAnimationInfoWithJsonName:(NSString *)jsonName {
    NSError *error;
    NSString *filePath = [[NSBundle mainBundle] pathForResource:jsonName ofType:@"json"];
    NSData *jsonData = [[NSData alloc] initWithContentsOfFile:filePath];
    
    if (@available(iOS 9.0, *)) {
        if (!jsonData) {
            jsonData = [[NSDataAsset alloc] initWithName:jsonName].data;
        }
    }
    NSDictionary *jsonObject = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData
                                                                          options:0 error:&error] : nil;
    return jsonObject;
}

#pragma mark - 动画播放过程中实时调用
- (void)startDisplayLink{
    self.displayLink = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self]
                                                   selector:@selector(handleDisplayLink:)];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop]
                           forMode:NSDefaultRunLoopMode];
    
}

- (void)handleDisplayLink:(CADisplayLink *)displayLink{
    
    if (self.isStop) {
        [self stopDisplayLink];
        return;
    }
    
    if ([self.delegate respondsToSelector:@selector(animationViewDidPlay:)]) {
        [self.delegate animationViewDidPlay:self];
    }
    
    if ([self.delegate respondsToSelector:@selector(animationViewDidPlay:jsonName:)]) {
        [self.delegate animationViewDidPlay:self jsonName:self.animationJson];
    }
    
    NSLog(@"%s",__FUNCTION__);
}

- (void)stopDisplayLink{
    [self.displayLink invalidate];
    self.displayLink = nil;
}

#pragma mark - 转换动画中指定元素的layer的frame到animtionView的layer上
/**
 转换动画中指定元素的layer的frame到animtionView的layer上
 方便添加自定义控件，以及通过动画的实时方法来达到自定义控件与动画中指定元素layer的frame保持一致，从而达到自定义控件与其动画效果一致，并且可以交互。
 @param elementLayer 必须与动画中的图层绑定，例如：与[self.animationView addSubview:elementLayerInView toKeypathLayer:keypath] 这个方法中的keypath绑定
 */
- (CGRect)convertElementLayerFrameToAnimationLayer:(CALayer *)elementLayer{
    [self.playView layoutIfNeeded];
    CGRect convertF = [elementLayer convertRect:elementLayer.frame toLayer:self.playView.layer];
    return convertF;
}

#pragma mark - 其他相关
- (CGFloat)pptW {
    return [LiveSizeConfig getPPTWidth];
}

- (CGFloat)pptH {
    return [LiveSizeConfig getPPTHeight];
}

- (CGFloat)pptLeft {
    return [LiveSizeConfig getHorizontalSpace];
}

- (CGFloat)pptTop {
    return [LiveSizeConfig getVerticalSpace];
}

- (void)dealloc {
    NSLog(@"%s",__FUNCTION__);
}

@end


@implementation WXLOTAnimationView
@end
